package com.lgmshare.k3.helper;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.ExifInterface;
import android.os.Build;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class ImageHelper {
    //图片分辨率
    private static final int MAX_PIXELS = 1200 * 1200;
    private static final int MAX_PIXELS_HQ = 1500 * 1500;
    //图片质量
    private static final int JPEG_QUALITY = 80;
    private static final int JPEG_QUALITY_HQ = 90;
    private static final int JPEG_QUALITY_LOW = 55;

    /**
     * 图片保存
     *
     * @param bitmap
     * @param fileName
     * @throws IOException
     */
    public static void save(Bitmap bitmap, String fileName) throws IOException {
        save(bitmap, fileName, Bitmap.CompressFormat.JPEG, JPEG_QUALITY_HQ);
    }

    /**
     * 图片保存
     *
     * @param bitmap
     * @param fileName
     * @param format
     * @param quality
     * @throws IOException
     */
    public static void save(Bitmap bitmap, String fileName, Bitmap.CompressFormat format, int quality) throws IOException {
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(fileName);
            bitmap.compress(format, quality, outputStream);
            outputStream.close();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 图片保存
     *
     * @param bitmap
     * @return
     */
    public static byte[] save(Bitmap bitmap) {
        return save(bitmap, Bitmap.CompressFormat.JPEG, JPEG_QUALITY_LOW);
    }

    /**
     * 图片保存
     *
     * @param bitmap
     * @param format
     * @param quality
     * @return
     */
    public static byte[] save(Bitmap bitmap, Bitmap.CompressFormat format, int quality) {
        ByteArrayOutputStream outputStream = null;
        try {
            outputStream = new ByteArrayOutputStream();
            bitmap.compress(format, quality, outputStream);
            return outputStream.toByteArray();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 获取优化后bitmap
     *
     * @param fileName
     * @return
     */
    public static Bitmap load(String fileName) {
        int scale = getScaleFactor(getImageSize(fileName), MAX_PIXELS);

        BitmapFactory.Options o = new BitmapFactory.Options();

        o.inScaled = false;
        o.inSampleSize = scale;
        o.inPreferredConfig = Bitmap.Config.ARGB_8888;

        if (Build.VERSION.SDK_INT >= 10) {
            o.inPreferQualityOverSpeed = true;
        }

        if (Build.VERSION.SDK_INT >= 11) {
            o.inMutable = true;
        }

        if (!new File(fileName).exists()) {
            return null;
        }

        Bitmap bitmap = BitmapFactory.decodeFile(fileName, o);
        if (bitmap == null) {
            return null;
        }

        try {
            ExifInterface exif = new ExifInterface(fileName);
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
            bitmap = fixExif(bitmap, orientation);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bitmap;
    }

    /**
     * 图片旋转修复
     *
     * @param bitmap
     * @param exifOrientation
     * @return
     */
    private static Bitmap fixExif(Bitmap bitmap, int exifOrientation) {
        try {
            final Matrix bitmapMatrix = new Matrix();
            switch (exifOrientation) {
                case 1:
                    break;  // top left
                case 2:
                    bitmapMatrix.postScale(-1, 1);
                    break;  // top right
                case 3:
                    bitmapMatrix.postRotate(180);
                    break;  // bottom right
                case 4:
                    bitmapMatrix.postRotate(180);
                    bitmapMatrix.postScale(-1, 1);
                    break;  // bottom left
                case 5:
                    bitmapMatrix.postRotate(90);
                    bitmapMatrix.postScale(-1, 1);
                    break;  // left top
                case 6:
                    bitmapMatrix.postRotate(90);
                    break;  // right top
                case 7:
                    bitmapMatrix.postRotate(270);
                    bitmapMatrix.postScale(-1, 1);
                    break;  // right bottom
                case 8:
                    bitmapMatrix.postRotate(270);
                    break;  // left bottom
                default:
                    break;  // Unknown
            }

            // Create new bitmap.
            return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), bitmapMatrix, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取图片缩放比例
     *
     * @param size
     * @param maxPixels
     * @return
     */
    private static int getScaleFactor(BitmapSize size, int maxPixels) {
        int scale = 1;
        int scaledW = size.getWidth();
        int scaledH = size.getHeight();
        while (scaledW * scaledH > maxPixels) {
            scale *= 2;
            scaledH /= 2;
            scaledW /= 2;
        }
        return scale;
    }

    /**
     * 获取图片尺寸
     *
     * @param fileName
     * @return
     */
    private static BitmapSize getImageSize(String fileName) {
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(fileName, o);
        if (o.outWidth == 0 || o.outHeight == 0) {
            return null;
        }

        int w = o.outWidth;
        int h = o.outHeight;

        try {
            ExifInterface exif = new ExifInterface(fileName);
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
            if (orientation == 5 || orientation == 6 || orientation == 7 || orientation == 8) {
                w = o.outHeight;
                h = o.outWidth;
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return new BitmapSize(w, h);
    }

    public static Bitmap scaleFit(Bitmap bitmap, int maxW, int maxH) {
        float ratio = Math.min(maxW / (float) bitmap.getWidth(), maxH / (float) bitmap.getHeight());
        int newW = (int) (bitmap.getWidth() * ratio);
        int newH = (int) (bitmap.getHeight() * ratio);
        return scale(bitmap, newW, newH);
    }

    public static Bitmap scale(Bitmap bitmap, int dw, int dh) {
        Bitmap res = Bitmap.createBitmap(dw, dh, Bitmap.Config.ARGB_8888);
        scale(bitmap, res);
        return res;
    }

    public static void scale(Bitmap src, Bitmap dest) {
        scale(src, dest, Color.TRANSPARENT);
    }

    public static void scale(Bitmap src, Bitmap dest, int clearColor) {
        scale(src, dest, clearColor, 0, 0, src.getWidth(), src.getHeight(), 0, 0, dest.getWidth(), dest.getHeight());
    }

    public static void scale(Bitmap src, Bitmap dest, int clearColor,
                             int x, int y, int sw, int sh,
                             int dx, int dy,
                             int dw, int dh) {
        dest.eraseColor(clearColor);
        Canvas canvas = new Canvas(dest);
        Paint paint = new Paint();
        paint.setFilterBitmap(true);
        canvas.drawBitmap(src, new Rect(x + 1, y + 1, sw - 1, sh - 1), new Rect(dx, dy, dw, dh), paint);
        canvas.setBitmap(null);
    }

    /**
     * 压缩图片
     *
     * @param imageFile       图片文件
     * @param reqWidth        图片最大宽度
     * @param reqHeight       图片最大高度
     * @param compressFormat  图片格式
     * @param quality         图片质量
     * @param destinationPath 指定压缩后图片保存路径
     * @return
     * @throws IOException
     */
    public static File compress(File imageFile, int reqWidth, int reqHeight, Bitmap.CompressFormat compressFormat, int quality, String destinationPath) throws IOException {
        FileOutputStream fileOutputStream = null;
        File file = new File(destinationPath).getParentFile();
        if (file != null && !file.exists()) {
            file.mkdirs();
        }
        try {
            fileOutputStream = new FileOutputStream(destinationPath);
            // write the compressed bitmap at the destination specified by destinationPath.
            decodeSampledBitmapFromFile(imageFile, reqWidth, reqHeight).compress(compressFormat, quality, fileOutputStream);
        } finally {
            if (fileOutputStream != null) {
                fileOutputStream.flush();
                fileOutputStream.close();
            }
        }

        return new File(destinationPath);
    }

    public static Bitmap decodeSampledBitmapFromFile(File imageFile, int reqWidth, int reqHeight) throws IOException {
        // First decode with inJustDecodeBounds=true to check dimensions
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;

        Bitmap scaledBitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);

        //check the rotation of the image and display it properly
        ExifInterface exif;
        exif = new ExifInterface(imageFile.getAbsolutePath());
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
        Matrix matrix = new Matrix();
        if (orientation == 6) {
            matrix.postRotate(90);
        } else if (orientation == 3) {
            matrix.postRotate(180);
        } else if (orientation == 8) {
            matrix.postRotate(270);
        }
        scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
        return scaledBitmap;
    }

    private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

    private static class BitmapSize {
        private int width;
        private int height;

        private BitmapSize(int width, int height) {
            this.width = width;
            this.height = height;
        }

        public int getWidth() {
            return width;
        }

        public int getHeight() {
            return height;
        }
    }
}